/**
 * @module NGS
 * @author Kevin.MOU
 */
"use strict";
define(function() {
	/**
	 * 变量监听器，用于在实例中对各种属性改变进行消息双向传递： 控件 - 实例
	 * @class DataBinder
	 * @constructor
	 */
	var DataBinder = function() {
		this.runtimes = {};
		return this;
	},
	
	fireCtl = function(propertyName, runtime, e, ctl) {
		var o = runtime.binder[propertyName];
		if (o && o.length > 0) {
			$.each(o, function(i, listener) {
				if (listener.ctl !== ctl && $.isFunction(listener.callback)) {
					if ($E.debug) {
						if (listener.ctl.type)
							console.log('事件 - 变量[' + propertyName + '], 监听者：[' + listener.ctl.type + '@' + listener.ctl.path + ']' + (ctl?(', 来源: [' + ctl.type + '@' + ctl.path + ']'):''), e.data);
						else
							console.log('事件 - 变量[' + propertyName + '], 监听者：[' + listener.ctl.id + ']' + (ctl?(', 来源: [' + ctl.type + '@' + ctl.path + ']'):''), e.data);
					}
					listener.callback(e, runtime);
				}
			})
		}
		
		if (runtime.pgBinder) {
			o = runtime.pgBinder[propertyName];
			if (o) {
				console.log('事件-属性组监听 [' + propertyName + ']');
				$.each(o, function(i, listener) {
					if ($.isFunction(listener.callback)) {
						listener.callback(propertyName, e, runtime);
					}
				})
			}
		}
	};

	DataBinder.prototype = {
		/**
		 * 注册变量监听器 - 控件
		 * @method register
		 * @param propertyName {string} 变量名
		 * @param runtime {object} 运行环境
		 * @param e {object} 注册的事件对象
		 */
		register : function(propertyName, runtime, e) {
			this.runtimes[runtime.namespace] = runtime;
			
			propertyName = propertyName.toLowerCase();
			if (! runtime.binder[propertyName])
				runtime.binder[propertyName] = [];
			var o = runtime.binder[propertyName];
			for(var i=0; i<o.length; i++){
				if (o[i].ctl.id === e.ctl.id) {
					//console.log(o[i].ctl);
					//console.log(e.ctl)
					//throw new Error('发现在[' + propertyName + ']上的重复监听器：' + e.ctl.id + '@' + runtime.struct.id);
					o[i] = e;
					return;
				}
			}
			o.push(e);
		},
		
		/**
		 * 注册变量监听器 - 非控件
		 * @method register
		 * @param propertyName {string} 变量名
		 * @param runtime {object} 运行环境
		 * @param e {object} 注册的事件对象
		 */
		registerPg : function(propertyName, runtime, e) {
			this.runtimes[runtime.namespace] = runtime;
			propertyName = propertyName.toLowerCase();
			if (! runtime.pgBinder)
				runtime.pgBinder = {};
			if (! runtime.pgBinder[propertyName])
				runtime.pgBinder[propertyName] = [];
			runtime.pgBinder[propertyName].push(e);
		},
		
		/**
		 * 移除所有监听器
		 * @method clear
		 */
		clear : function() {
			this.runtimes = {};
		},

		/**
		 * 触发属性改变消息通知，将属性值改变通知给监听的控件
		 * @method fireCtl
		 * @param propertyName {string} 变量名
		 * @param runtime {object} 运行环境
		 * @param e {object} 消息内容对象
		 * @param ctl {object} 触发消息的对象
		 * e : {
		 * 	type: (0=普通值消息，1=二维数组值消息)
		 * 	data: 普通值或Map 
		 *	{
		 * 		k: 行,列
		 * 		v: 值
		 *	}
		 * }
		 */
		fireCtl : function(propertyName, runtime, e, ctl, noIncludeExternal) {
			// console.log('Databind - fireCtl', propertyName)
			propertyName = propertyName.toLowerCase();
			var isLocal = propertyName.startWith('var') || propertyName.startWith('tabc');
			if (isLocal) {
				fireCtl(propertyName, runtime, e, ctl);
			} else {
				for(var key in this.runtimes) {
					fireCtl(propertyName, this.runtimes[key], e, ctl);
				}
				
				if (noIncludeExternal)
					return;
				
				// 通知外部监听器
				for(var ex in runtime.instance.externalListener) {
					// console.log('fire property listener[' + ex + '], property=' + propertyName);
					runtime.instance.externalListener[ex](propertyName, (e.type == 0) ? e.data : runtime.instance.getValue(propertyName, runtime));
				}
			}
		}
	};

	return {
		create : function() {
			return new DataBinder();
		}
	}
})
